#include "slave.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bsp_uart_fifo.h"

typedef struct
{
	uint8_t RxBuf[AGILE_MODBUS_MAX_ADU_LENGTH];
	uint16_t RxCount;
	uint8_t TxBuf[AGILE_MODBUS_MAX_ADU_LENGTH];
	uint16_t TxCount;
    uint8_t timeout_flag;
    uint8_t timeout_cnt;

}MODS_T;

agile_modbus_rtu_t ctx_rtu;
agile_modbus_t *ctx = &ctx_rtu._ctx;
uint8_t ctx_send_buf[AGILE_MODBUS_MAX_ADU_LENGTH];
uint8_t ctx_read_buf[AGILE_MODBUS_MAX_ADU_LENGTH];

MODS_T g_tModS;


void rtu_slave_task(void)
{
    // 空闲中断
    if(g_tModS.timeout_flag == 0)
        return;
    g_tModS.timeout_flag = 0;

    // 拷贝接收数据
    memcpy(ctx->read_buf, g_tModS.RxBuf, g_tModS.RxCount);
    ctx->read_bufsz = g_tModS.RxCount;
    g_tModS.RxCount = 0;

    // 解析回调
    int send_len = agile_modbus_slave_handle(ctx, ctx->read_bufsz, 0, agile_modbus_slave_util_callback, &slave_util, NULL);
    // 清除发送缓存区
    comClearTxFifo(COM2);
    // 发送数据
    if (send_len > 0)
        comSendBuf(COM2, ctx->send_buf, send_len);

}

void rtu_slave_init(void)
{
    agile_modbus_rtu_init(&ctx_rtu, ctx_send_buf, sizeof(ctx_send_buf), ctx_read_buf, sizeof(ctx_read_buf));
    agile_modbus_set_slave(ctx, 1);
}


void modbus_timeout_cnt(void)
{
    if(g_tModS.timeout_cnt)
    {
        g_tModS.timeout_cnt--;
        if(g_tModS.timeout_cnt == 0)
        {
            g_tModS.timeout_flag = 1;
        }
    }
        
}

/*
*********************************************************************************************************
*	函 数 名: MODS_ReciveNew
*	功能说明: 串口接收中断服务程序会调用本函数。当收到一个字节时，执行一次本函数。
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void MODS_ReciveNew(uint8_t _byte)
{
	/*
		3.5个字符的时间间隔，只是用在RTU模式下面，因为RTU模式没有开始符和结束符，
		两个数据包之间只能靠时间间隔来区分，Modbus定义在不同的波特率下，间隔时间是不一样的，
		所以就是3.5个字符的时间，波特率高，这个时间间隔就小，波特率低，这个时间间隔相应就大

		4800  = 7.297ms
		9600  = 3.646ms
		19200  = 1.771ms
		38400  = 0.885ms
	*/
	uint32_t timeout;

	g_tModS.timeout_flag = 0;
	
	timeout = 35000000 / 9600;			/* 计算超时时间，单位us 35000000*/
	
	// /* 硬件定时中断，定时精度us 硬件定时器1用于ADC, 定时器2用于Modbus */
	// bsp_StartHardTimer(1, timeout, (void *)MODS_RxTimeOut);

    g_tModS.timeout_cnt = timeout/1000 + 2; // 大概5ms

	if (g_tModS.RxCount < AGILE_MODBUS_MAX_ADU_LENGTH)
	{
		g_tModS.RxBuf[g_tModS.RxCount++] = _byte;
	}
}







